package chatModel;

import java.io.File;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;
import messages.*;
import chatNI.*;
import java.lang.Object;

import javax.rmi.CORBA.Util;
import javax.swing.DefaultListModel;

/**
 * Classe définissant l'utilisateur LOCAL
 * Utilisateur est observable pour que le ChatNI et le ChatGUI décident des
 * actions à mener par rapport aux notifications des utilisateurs
 */
public class Utilisateur extends Observable {
        
	private String userName;
	private InetAddress myIp;

	// c'est le modele possède une liste d'observer où il y aura les 2 observer, le ChatGui et le ChatNI
	private ArrayList <Observer> listeDesObserver = new ArrayList<Observer>();
	private DefaultListModel listeUser = new DefaultListModel();
	//private HashMap<UtilisateurDistant,String> Conversation = new HashMap<UtilisateurDistant,String>();

	private File file;
	private String msgDansFenetre;
	private int choix;

	private byte[] msgToSend;

	private InetAddress adresseIPUtilisateurDistant;
	private String nameFileProposed; //inutile je pense car on peut extraire le nom du fichier depuis le ficher 
	private UtilisateurDistant userDistant;
        
        /**
         * Constructeur
         * @param userName Pseudo de l'utilisateur local
         * @param myIp Adresse IP locale
         */
	public Utilisateur(String userName, InetAddress myIp) {
		super();
		this.userName = userName;
		this.myIp = myIp;

	}
        
        /**
         * Permet d'obtenir la DefaultModelList
         * @return DefautModelList de l'utilisateur local
         */
	public DefaultListModel getListeUser() {
		return listeUser;
	}
        
        /**
         * Permet de changer la DefaultListModel
         * @param listeUser DefaultListModel
         */
	public void setListeUser(DefaultListModel listeUser) {
		this.listeUser = listeUser;
	}

        /**
         * Permet d'obtenir les messages dans la fenêtre pour le GUI
         * @return 
         */
	public String getMsgDansFenetre() {
		return msgDansFenetre;
	}


/*	public void setConversation(HashMap<UtilisateurDistant, String> conversation) {
		Conversation = conversation;
	}

	public HashMap<UtilisateurDistant, String> getConversation() {
		return Conversation;
	}*/

        /**
         * Permet d'obtenir le pseudo de l'utilisateur local
         * @return Nom d'utilisateur
         */
	public String getUserName() {
		return userName;
	}
        
        /**
         * Permet d'initialiser le nom de l'utilisateur local si non défini
         * dans le constructeur
         * @param userName Pseudo de l'utilisateur local
         */
	public void setUserName(String userName) {
		this.userName = userName;
	}
        
        /**
         * Permet d'initialiser le nom de l'utilisateur local si non définie
         * dans le constructeur
         * @param myIp Adresse IP locale
         */
	public void setMyIp(InetAddress myIp) {
		this.myIp = myIp;
	}
        
        /**
         * Permet d'obtenir l'adresse IP locale
         * @return Adresse IP locale
         */
	public InetAddress getMyIp() {
		return myIp;
	}

/*	public String getMessageConversation(UtilisateurDistant otherUser) {
		return this.Conversation.get(otherUser);
	}*/
        
        /**
         * Permet d'obtenir le Choix à faire lors des notifications
         * @see chatNI.ChatNI#update(java.util.Observable, java.lang.Object) update dans ChatNI
         * @see chatGUI.ChatGUI#update(java.util.Observable, java.lang.Object) update dans ChatGUI
         * @return Valeur du choix
         */
	public int getChoix(){
		return this.choix;
	}
        
        /**
         * Renvoi le futur message à envoyer à un ou des utilisateurs distants
         * @return Message à envoyer
         */
	public byte[] getMsgToSend(){
		return this.msgToSend;
	}
        
        /**
         * Renvoi l'adresse IP de l'utilisateur distant à qui on doit envoyer le
         * message
         * @return Adresse IP du destinataire
         */
	public InetAddress getAdresseIPUtilisateurDistant(){
		return this.adresseIPUtilisateurDistant;
	}
	
        /**
         * Donne le nom du fichier proposé
         * @return Nom du fichier
         */
	public String getNameFileProposed(){
		return this.nameFileProposed;
	}
        
        /**
         * Permet d'obtenir le destinataire
         * @return l'utilisateur distant
         */
	public UtilisateurDistant getUserDistant() {
		return this.userDistant;
	}

	/**
         * Permet d'obtenir le fichier proposé
         * @return Fichier proposé
         */
	public File getFile() {
		return file;
	}

        /**
         * Envoi une notification de connexion
         * @see chatNI.ChatNI#update(java.util.Observable, java.lang.Object) update
         * @see chaGUI.ChatGUI#update(java.util.Observable, java.lang.Object) update
         */
	public void connect(){

		//traiter cette notification dans le gui et dans le NI => changer de fenetre et lancer la connexion depuis le ChatNI
		this.choix=Choix.connexionOk;
		System.out.println("connect user");
		this.setChanged();
		this.notifyObservers(this);
	}
        
        /**
         * Envoi une notification de déconnexion
         * @see chatNI.ChatNI#update(java.util.Observable, java.lang.Object) update
         * @see chaGUI.ChatGUI#update(java.util.Observable, java.lang.Object) update
         */
	public void disconnect(){
		this.choix=Choix.deconnexionOk;
		this.listeUser.clear();
		this.setChanged();
		this.notifyObservers(this);
	}
	
        /**
         * Envoi une notification pour le GUI
         * @see chatGUI.ChatGUI#update(java.util.Observable, java.lang.Object) update
         * @param user Utilisateur distant
         * @param msg Message de l'utilisateur distant (Pour les connexions et déconnexions)
         */
	public void afficheConnectDeconnect(UtilisateurDistant user, String msg){
		this.userDistant=user;
		this.msgDansFenetre = msg;
		this.choix=Choix.connectdeconnect;
		this.setChanged();
		this.notifyObservers(this);
	}
	
        /**
         * Notification pour lors de la déconnexion ou fermeture du Chat
         * @see chatNI.ChatNI#update(java.util.Observable, java.lang.Object) update
         */
	public void close(){
		System.out.println("envoie quitte");
		this.choix=Choix.quitChat;
		this.setChanged();
		super.notifyObservers(this);
	}
	
        /**
         * Notification pour l'envoi de message
         * @see chatGUI.ChatGUI#update(java.util.Observable, java.lang.Object) update
         * @see chatNI.ChatNI#update(java.util.Observable, java.lang.Object) update
         * @param user Utilisateur destinataire du message (Cela peut être également tous les utilisateur)
         * @param msg Message à envoyer
         */
	public void sendMsgToNIandGUI(UtilisateurDistant user, String msg){
		this.userDistant=user;
		this.msgDansFenetre=msg;
		if(user.getUserName().compareTo("All Users")==0){
			this.choix = Choix.sendMsgAllUser;
		}else
			this.choix=Choix.sendMsgOneUser;
		try {
			this.msgToSend = MessagesFactory.getChatMessage(this.userName, msg);
		} catch (MessageCreationException e) {
			System.out.println("Probleme création message dans sendMsgToNI");
			e.printStackTrace();
		}
		this.setChanged();
		super.notifyObservers(this);
	}
        
        /**
         * Notification pour envoyer une proposition de fichier
         * @see chatNI.ChatNI#update(java.util.Observable, java.lang.Object) update
         * @param user Utilisateur distant
         * @param file Fichier à proposer
         */
	public void sendDemandeFileToNI(UtilisateurDistant user, File file){
		this.userDistant=user;
		this.file = file;
		this.msgDansFenetre="Vous avez envoyé une demande de reception de fichier à " + user.getUserName();
		if(user.getUserName().compareTo("All Users")==0){
			this.choix = Choix.sendFileNotifAllUser;
		}else
			this.choix=Choix.sendFileNotifOneUser;
		try {
			this.msgToSend = MessagesFactory.getFileNotif(this.userName, file.getName(), true, false);
		} catch (MessageCreationException e) {
			System.out.println("Probleme création message dans sendMsgToNI");
			e.printStackTrace();
		}
		this.setChanged();
		super.notifyObservers(this);
	}
        
        
        /**
         * Notification pour indiquer si le fichier a été envoyé ou reçu
         * @see chatGUI.ChatGUI#update(java.util.Observable, java.lang.Object) update
         * @param user Utilisateur distant
         * @param msg Message de notification
         */
	public void fichierEnvoyeOuRecu(UtilisateurDistant user, String msg){
		this.userDistant=user;
		this.msgDansFenetre=msg;
		this.choix = Choix.fichierRecuOuEnvoye;
		
		this.setChanged();
		this.notifyObservers(this);
	}
	
        /**
         * Notifie le GUI pour indiquer qu'un nouveau message est arrivé
         * @see chatGUI.ChatGUI#update(java.util.Observable, java.lang.Object) update
         * @param distantUser Utilisateur distant emetteur
         * @param newMsg Nouveau message arrivé
         */
	public void notifyGUINewMsg(UtilisateurDistant distantUser, String newMsg) {
		this.userDistant=distantUser;
		this.msgDansFenetre=newMsg;
		this.choix=Choix.rcvMsg;
		this.setChanged();
		this.notifyObservers(this);//Pour le Chat GUI dans l'update il faut afficher les message
	}
        
        /**
         * Notifie le GUI pour proposition de fichier
         * @see chatGUI.ChatGUI#update(java.util.Observable, java.lang.Object) update
         * @param distantUser Utilisateur proposant le fichier
         * @param nameFile Nom du fichier proposé
         */
	public void notifyGUIFileRequest(UtilisateurDistant distantUser, String nameFile) {
		this.userDistant=distantUser;
		this.nameFileProposed = nameFile;
		this.choix=Choix.fileNotif;
		this.setChanged();
		this.notifyObservers(this);
	}
        
        /**
         * Notifie le chatNI pour lui dire d'envoyer une notification 
         * pour accepter le fichier
         * @param user Utilisateur distant qui a envoyé le fichier
         * @param file Fichier futur pour la réception
         */
	public void acceptFileToNI(UtilisateurDistant user, File file){
		this.userDistant=user;
		this.msgDansFenetre="Vous avez accepté le fichier de " + user.getUserName();
		this.choix=Choix.confAcceptFileOk;
		this.file=file;
		try {
			this.msgToSend = MessagesFactory.getFileNotif(this.userName, file.getName(), false, true);
		} catch (MessageCreationException e) {
			System.out.println("Probleme création message dans sendMsgToNI");
			e.printStackTrace();
		}
		this.setChanged();
		super.notifyObservers(this);
	}
        
        /**
         * Notifie le chatNI pour lui dire d'emettre le fichier
         * @see chatNI.ChatNI#update(java.util.Observable, java.lang.Object) update
         * @param user Utilisateur qui doit recevoir le fichier
         * @param nameFile Nom du fichier concerné
         */
	public void notifyNISendFile(UtilisateurDistant user, String nameFile){
		this.userDistant=user;
		this.msgDansFenetre=user.getUserName() + " a accepté de recevoir votre fichier " + nameFile;
		this.choix=Choix.rcvAcceptedFile;
		this.setChanged();
		super.notifyObservers(this);
	}
	
        /**
         * Notifie le GUI pour lui dire que le fichier proposé a été refusé
         * @see chatGUI.ChatGUI#update(java.util.Observable, java.lang.Object) update
         * @param user Utilisateur distant qui a refusé notre fichier
         * @param nameFile Nom du fichier refusé
         */
	public void notifyGUIFileRefused(UtilisateurDistant user, String nameFile){
		this.userDistant=user;
		this.msgDansFenetre=user.getUserName() + " a refusé de recevoir votre fichier " + nameFile;
		this.choix=Choix.rcvRefusedFile;
		this.setChanged();
		super.notifyObservers(this);
	}
	
        /**
         * Notifie le chatNI pour lui dire qu'on refuse le fichier proposé
         * @see chatNI.ChatNI#update(java.util.Observable, java.lang.Object) update
         * @param user Utilisateur distant qui nous a proposé un fichier
         * @param nameFile Nom du fichier proposé
         */
	public void refuseFileToNI(UtilisateurDistant user, String nameFile){
		this.userDistant=user;
		this.msgDansFenetre="Vous avez refusé le fichier de " + user.getUserName();
		this.choix=Choix.confAcceptFileNoOk;
		try {
			this.msgToSend = MessagesFactory.getFileNotif(this.userName, nameFile, false, false);
		} catch (MessageCreationException e) {
			System.out.println("Probleme création message dans sendMsgToNI");
			e.printStackTrace();
		}
		this.setChanged();
		super.notifyObservers(this);
	}
        
        /**
         * Notifie le chatNI pour envoyer un Hello négatif 
         * (Réponse à un Hello positif)
         * @see chatNI.ChatNI#update(java.util.Observable, java.lang.Object) update
         * @param destinataire Utilisateur qui vient de nous envoyer un Hello positif
         * @throws MessageCreationException Erreur lors de la création du Hello négatif
         */
	public void notifyChatNISendNegHello(UtilisateurDistant destinataire) throws MessageCreationException {
		System.out.println("Construction d'un Hello Negatif");
		this.choix = Choix.rcvNewHello;
		this.userDistant= destinataire;
		this.msgToSend = MessagesFactory.getHello(this.userName, false);
		//ça s'adresse au NI qui envoie le hello
		super.setChanged();
		super.notifyObservers(this);

		this.setChanged();
		this.notifyObservers(this);
		
	}

}
